#include <iostream>


//这段代码展示了一个简单的AST优化，即在 AST 中进行算术表达式的简化。
// 该优化可以通过递归遍历 AST 中的节点来实现。对于二元运算符节点，若其两个子节点均为数字节点，则可以将它们的值计算出来，生成一个新的数字节点代替原有节点。
// 对于一元运算符节点，若其子节点为数字节点，则可以将它的值计算出来，生成一个新的数字节点代替原有节点。对于其他类型的节点，递归遍历其子节点即可。
enum ExprType {Base,BinaryOp,Number,UnaryOp};
enum OpType {Add,Subtract,Multiply,Divide,Positive,Negative};
// AST节点定义
class Expr {
public:
    virtual ExprType getType() = 0;
    virtual ~Expr() = default;
    virtual void replaceWith(Expr*);
    virtual int eval() const = 0;
    virtual Expr* getChildren();
};

class NumberExpr : public Expr {
public:
    NumberExpr(int val) : value(val) {}
    int eval() const override { return value; }
    ExprType getType() override{ return ExprType::Number;}
private:
    int value;
};

class BinaryExpr : public Expr {
public:
    BinaryExpr(Expr* l, Expr* r, char op) : left(l), right(r), op(op) {}
    ~BinaryExpr() override {
        delete left;
        delete right;
    }
    ExprType getType() override{ return ExprType::BinaryOp;}
    int eval() const override {
        int l = left->eval();
        int r = right->eval();
        switch(op) {
            case '+': return l + r;
            case '-': return l - r;
            case '*': return l * r;
            case '/': return l / r;
        }
        return 0;
    }
    Expr* getLeft(){
        //doSomething
    }
    Expr* getRight(){
        //doSomething
    }
    OpType getOp(){
        //doSomething
    }
private:
    Expr* left;
    Expr* right;
    char op;
};


class UnaryOpExpr : public Expr {
public:
    ExprType getType() override{ return ExprType::UnaryOp;}
    int eval() const override {
        int l = left->eval();
        int r = right->eval();
    }
    Expr* getExpr(){
        //doSomething
    }
    Expr* getOp(){
        //doSomething
    }
private:
    Expr* left;
    Expr* right;
    char op;
};

void simplifyArithmetic(Expr* Expr) {
    if (Expr->getType() == ExprType::BinaryOp) {
        auto BinaryExpr = static_cast<BinaryExpr*>(Expr);
        if (BinaryExpr->getLeft()->getType() == ExprType::Number && BinaryExpr->getRight()->getType() == ExprType::Number) {
            // 若两个操作数均为数字，则可以进行计算，将结果更新为新的数字节点
            auto left = static_cast<NumberExpr*>(BinaryExpr->getLeft())->eval();
            auto right = static_cast<NumberExpr*>(BinaryExpr->getRight())->eval();
            double result = 0.0;
            switch (BinaryExpr->getOp()) {
                case OpType::Add:
                    result = left + right;
                    break;
                case OpType::Subtract:
                    result = left - right;
                    break;
                case OpType::Multiply:
                    result = left * right;
                    break;
                case OpType::Divide:
                    result = left / right;
                    break;
                default:
                    break;
            }
            auto resultExpr = new NumberExpr(result);
            Expr->replaceWith(resultExpr);
            delete Expr;
            Expr = resultExpr;
        } else {
            // 递归处理子节点
            simplifyArithmetic(BinaryExpr->getLeft());
            simplifyArithmetic(BinaryExpr->getRight());
        }
    } else if (Expr->getType() == ExprType::UnaryOp) {
        // 对于一元运算符，也可以进行简化
        auto unaryOpExpr = static_cast<UnaryOpExpr*>(Expr);
        if (unaryOpExpr->getExpr()->getType() == ExprType::Number) {
            auto numberExpr = static_cast<NumberExpr*>(unaryOpExpr->getExpr());
            double result = 0.0;
            switch (unaryOpExpr->getOp()) {
                case OpType::Positive:
                    result = numberExpr->eval();
                    break;
                case OpType::Negative:
                    result = -numberExpr->eval();
                    break;
                default:
                    break;
            }
            auto resultExpr = new NumberExpr(result);
            Expr->replaceWith(resultExpr);
            delete Expr;
            Expr = resultExpr;
        } else {
            simplifyArithmetic(unaryOpExpr->getExpr());
        }
    } else {
        // 对于其他类型的节点，继续递归处理
        for (auto child : Expr->getChildren()) {
            simplifyArithmetic(child);
        }
    }
}
